ホームに戻る
出典 :
関連 :
目次 :
コンバーターとは
WPFのデータバインディングにおいて、ソースとターゲットとの間で形式(型や書式など)を変換する機構のこと。
例えば TextBox に DateTime 型をバインドし、そのうち年、月、日のみを表示するよう変換する、といったことが可能となる。
コンバーターの実装
コード
System.Windows.Data.IValueConverter
インタフェースを実装する。実装が必要なメソッドは以下のふたつ。
Convert()
- ソースからターゲットへの変換
ConvertBack()
- ターゲットからソースへの変換
変換先のプロパティ( Convert()
: ターゲット / ConvertBack()
: ソース )を更新しない場合は、return DependencyProperty.UnsetValue;
とする。
using System.Globalization;
using System.Windows.Data;
namespace _Converter;
// コンバーター
// DateTime ⇒ String
[ValueConversion(typeof(DateTime), typeof(String))]
public class DateConverter : IValueConverter
{
// ソース ⇒ ターゲット変換
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// 日付形式の文字列に変換して返す
DateTime date = (DateTime)value;
return date.ToShortDateString();
}
// ターゲット ⇒ ソース変換
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// 日時に変換可能であれば変換して返す
string strValue = value as string;
DateTime resultDateTime;
if (DateTime.TryParse(strValue, out resultDateTime))
{
return resultDateTime;
}
// 変換できない場合は何もしない
// (値を更新しない)
return DependencyProperty.UnsetValue;
}
}
Convert() / ConvertBack() の詳細
引数及び戻り値は下表のとおり。
|
Convert() |
ConvertBack() |
機能 |
ソース値をターゲット値に変換する (ソース値からターゲット値を得る) |
ターゲット値をソース値に変換する (ターゲット値からソース値を得る) |
戻り値 |
object |
(変換後の)ターゲット値 |
object |
(変換後の)ソース値 |
引数 |
object |
(変換前の)ソース値 |
object |
(変換前の)ターゲット値 |
Type |
変換後(ターゲット値)の型 |
Type |
変換後(ソース値)の型 |
object |
ConverterParameter として渡されたパラメータ |
object |
ConverterParameter として渡されたパラメータ |
CultureInfo |
ConverterCulture として渡されたカルチャ |
CultureInfo |
ConverterCulture として渡されたカルチャ |
ConverterParameter
およびConverterCulture
はデータバインディングの構成時に指定する。
省略時はともに、既定値であるnull
が格納される。いずれもConverter
のメンバではなく、Binding
のメンバである点に注意。
ConverterCulture
はロケールの情報を保持し、桁区切りや月日の並び順に影響する。多国籍対応を行う場合でなければ指定する必要は特に無い。
XAML
作成したコンバーターを親要素にリソースとして登録することで、デザインから参照することが可能となる。
このとき、コンバーターはStaticResource
とする必要がある(DynamicResource
はエラーとなる)。
<
Window
xmlns:conv=
"clr-namespace:_Converter">
:
<!-- コードで作成したコンバータ―をリソースに登録 -->
<!-- キー : dateConverter -->
<
Window.Resources>
<
conv:DateConverter
x:Key=
"dateConverter"/>
</
Window.Resources>
:
<!-- コンバーター(キー : dateConverter )を適用 -->
<!-- StaticResource として参照 -->
<
TextBlock Name=
"StartDateDTKey" Grid.Row=
"2" Grid.Column=
"1"
Text="{Binding
Path=StartDate,
Converter={
StaticResource dateConverter}}"
Style=
"{StaticResource textStyleTextBlock}"/>
:
</
Window>
応用#1 : ラジオボタンを双方向バインディングする

チェックされたラジオボタンに対応する列挙値(Enum)を取得したい場合、以下のように実装する。
PropertyChanged 、Reactive の実装は省略。
コード : コンバーターの定義
using System.Globalization;
using System.Windows.Data;
namespace _Converter
// 列挙体の定義
public enum mode
{
Simple,
Detail
}
// Enum ⇒ Bool 変換用コンバーター
public class EnumToBoolConverter : IValueConverter
{
// ソース ⇒ ターゲット変換
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var paramStr = parameter as string;
// 比較値が null または
// ソース値が定義域に含まれない場合は値を更新しない
if ( paramStr is null ||
!Enum.IsDefined(targetType, value) )
{
return DependencyProperty.UnsetValue;
}
// ソース値が比較値に一致すれば true 、
// そうでなければ false を返す
return Enum.Parse( value.GetType(), paramStr ).Equals(value);
}
// ターゲット ⇒ ソース変換
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var paramStr = parameter as string;
// 比較値が null または
// ターゲット値が true でない場合は値を更新しない
if( paramStr is null ||
!true.Equals( value ) )
{
return DependencyProperty.UnsetValue;
}
return Enum.Parse( targetType, paramStr );
}
}
XAML : ラジオボタンの配置、コンバーターの適用
<
Window
xmlns:res=
"clr-namespace:_Converter">
:
<
StackPanel>
<
StackPanel.Resources>
<!-- コンバーター EtoB 宣言 -->
<
res:EnumToBoolConverter
x:Key=
"EtoB" />
</
StackPanel.Resources>
<!-- RadioButton -->
<!-- ターゲット : IsChecked (bool) -->
<!-- ソース : ModeValue (mode) -->
<!-- コンバーター : EtoB -->
<!-- 「簡易」- ConverterParameter = Simple ( mode.Simple ) -->
<
RadioButton Content=
"簡易"
IsChecked=
"{Binding ModeValue, Converter={StaticResource EtoB}, Mode=TwoWay, ConverterParameter=Simple}" />
<!-- 「詳細」- ConverterParameter = Detail ( mode.Detail ) -->
<
RadioButton Content=
"詳細"
IsChecked=
"{Binding ModeValue, Converter={StaticResource EtoB}, Mode=TwoWay, ConverterParameter=Detail}" />
:
</
StackPanel>
:
</
Window>
解説

ソース値を変更すると
Convert()
が呼ばれ、ソース値が
value
に、
ConverterParameter
(
mode.Simple
または
mode.Detail
)が
parameter
に渡される。
parameter
を比較値として用い、
value
が
parameter
に一致する場合に
Convert()
が
true
を返すため、対応するラジオボタンがチェックされる。
逆にチェック状態を変更すると
ConvertBack()
が呼ばれ、
ConverterParameter
で指定された列挙子がソースに反映される。
注意が必要な点として、ラジオボタンのチェック状態を変更すると「チェックされた」ラジオボタンと、「チェックを外された」ラジオボタンの双方で
CheckedChanged
イベントが発生するため、
ConvertBack()
もそれぞれで(計2回)コールされる。
ソースに反映するのはチェックされたラジオボタンであるため、
value
が
true
(チェックされている)の場合のみソース値の変更を行う。
応用#2 : bool を指定した Visibility にバインドする
コントロールの可視性(Visibility
)をbool
値によって切り替えられるコンバーターの例を示す。
ソースがtrue
の場合はCollapsed
、false
の場合はVisible
を返すよう、TrueTo
、FalseTo
プロパティをリソース宣言時に指定している。
ここではTrueTo
、FalseTo
にデフォルト値を割り当てていないため、true
/false
に対応する値を用途に応じて切り替えることが可能であるが、
毎回指定する必要がある。
コード : コンバーターの定義
using System.Globalization;
using System.Windows.Data;
namespace _Converter;
public class BoolToAnyVisibilityConverter : IValueConverter
{
public Visibility? TrueTo { get; set; } //< ソースが true の場合に返す値
public Visibility? FalseTo { get; set; } //< ソースが false の場合に返す値
// ソース ⇒ ターゲット変換
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// TrueTo が設定されていない場合は例外
if (!TrueTo.HasValue)
{
throw new InvalidOperationException($"{nameof(TrueTo)}にVisibilityが設定されていません");
}
// FalseTo が設定されていない場合は例外
if (!FalseTo.HasValue)
{
throw new InvalidOperationException($"{nameof(FalseTo)}にVisibilityが設定されていません");
}
// ソースが bool でない場合は値を更新しない
if (!(value is bool b)) { return DependencyProperty.UnsetValue; }
// ソース(bool)が true の場合は TrueTo 、false の場合は FalseTo を返す
return b ? TrueTo : FalseTo;
}
// ターゲット ⇒ ソース変換 : 何もしない
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML : コンバーターの適用
ここでTrueTo
、FalseTo
に値を設定する。
<
Window
xmlns:res=
"clr-namespace:_Converter">
:
<
StackPanel>
<
StackPanel.Resources>
<!-- コンバーター宣言 -->
<!-- TrueTo に Collapsed 、FalseTo に Visible を設定 -->
<
res:BoolToAnyVisibilityConverter
x:Key=
"BoolToCollapse" TrueTo=
"Collapsed" FalseTo=
"Visible"/>
</
StackPanel.Resources>
:
</
StackPanel>
:
</
Window>